package com.dengdai.applibrary.sqlite;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;

import com.dengdai.applibrary.base.BaseApplication;
import com.dengdai.applibrary.data.BaseEntity;
import com.dengdai.applibrary.utils.LogUtils;
import com.j256.ormlite.android.AndroidDatabaseConnection;
import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.support.DatabaseConnection;
import com.j256.ormlite.table.TableUtils;

import java.sql.Savepoint;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @说明 数据库操作基类
 * @作者 LY
 * @时间 15/12/21 10:34
 * @版权 Copyright(c) 2015 LY-版权所有
 */
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
    private static String databaseName = "default_database.sqlite";
    private static int databaseVersion = 1;
    private static DatabaseHelper instance = null;
    private Map<String, Dao> daoMap = new HashMap<String, Dao>();
    private static List<Class<? extends BaseEntity>> table = new ArrayList<Class<? extends BaseEntity>>();


    /**
     * 对外实例化对象不采用该构造方法
     *
     * @param context
     */
    @Deprecated
    public DatabaseHelper(Context context) {
        super(context, databaseName, null, databaseVersion);
    }


    /**
     * 实例化对象
     *
     * @param dbName  数据库名称
     * @param version 数据库版本
     * @return
     */
    public static synchronized DatabaseHelper gainInstance(String dbName, int version) {
        if (instance == null) {
            databaseName = dbName;
            databaseVersion = version;
            // 会隐式调用public DatabaseHelper(Context context){}
            instance = OpenHelperManager.getHelper(BaseApplication.getAppContext(), DatabaseHelper.class);
        }
        return instance;
    }


    /**
     * 注册表实体
     *
     * @param entity 表实体
     */
    public static void registerTables(Class<? extends BaseEntity> entity) {
        table.add(entity);
    }

    /**
     * 创建表
     *
     * @param entity 实体
     */
    public void createTable(Class<? extends BaseEntity> entity) {
        try {
            TableUtils.createTableIfNotExists(getConnectionSource(), entity);
        } catch (Exception e) {
            LogUtils.e(e.getMessage());
        }
    }

    /**
     * 清除表数据
     *
     * @param entity 实体
     */
    public void clearTableData(Class<? extends BaseEntity> entity) {
        try {
            TableUtils.clearTable(getConnectionSource(), entity);
        } catch (Exception e) {
            LogUtils.e(e.getMessage());
        }
    }

    /**
     * 删除表
     *
     * @param entity 实体
     */
    public void dropTable(Class<? extends BaseEntity> entity) {
        try {
            TableUtils.dropTable(getConnectionSource(), entity, true);
        } catch (Exception e) {
            LogUtils.e(e.getMessage());
        }
    }

    /**
     * 获取数据库连接
     *
     * @return 数据库连接
     */
    public DatabaseConnection getConnection() {
        DatabaseConnection connection = null;
        try {
            if (isOpen()) {
                connection = getConnectionSource().getReadWriteConnection();
            } else {
                connection = new AndroidDatabaseConnection(getWritableDatabase(), true);
            }
        } catch (Exception e) {
            LogUtils.e(e.getMessage());
        }
        return connection;
    }

    /**
     * 关闭数据库连接
     */
    public void closeConnection(DatabaseConnection connection) {
        try {
            if (connection != null) {
                if (!connection.isClosed()) {
                    connection.close();
                }
            }
        } catch (Exception e) {
            LogUtils.e(e.getMessage());
        }
    }

    /**
     * 提交事务
     *
     * @param connection 数据库连接
     * @param savePoint  事务点
     */
    public void commit(DatabaseConnection connection, Savepoint savePoint) {
        try {
            connection.commit(savePoint);
        } catch (Exception e) {
            LogUtils.e(e.getMessage());
        }
    }

    /**
     * 回滚事务
     *
     * @param connection 数据库连接
     * @param savePoint  事务点
     */
    public void rollback(DatabaseConnection connection, Savepoint savePoint) {
        try {
            connection.rollback(savePoint);
        } catch (Exception e) {
            LogUtils.e(e.getMessage());
        }
    }

    /**
     * 获取Dao
     */
    public synchronized <D extends Dao<T, ?>, T> D getDao(Class<T> clazz) {
        Dao dao = null;
        try {
            String keyClassName = clazz.getSimpleName();
            if (daoMap.containsKey(keyClassName)) {
                dao = daoMap.get(keyClassName);
            }
            if (dao == null) {
                dao = super.getDao(clazz);
                daoMap.put(keyClassName, dao);
            }
        } catch (Exception e) {
            e.printStackTrace();
            LogUtils.i(e.getMessage());
        }
        return (D) dao;
    }

    /**
     * 释放数据库连接
     */
    public void releaseAll() {
        if (instance != null) {
            OpenHelperManager.releaseHelper();
            instance = null;
        }
    }

    /**
     * 释放资源
     */
    @SuppressWarnings("unused")
    @Override
    public void close() {
        super.close();
        for (String key : daoMap.keySet()) {
            Dao dao = daoMap.get(key);
            dao = null;
        }
    }


    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource) {
        try {
            for (Class<? extends BaseEntity> entity : table) {
                TableUtils.createTable(connectionSource, entity);
            }
        } catch (Exception e) {
            LogUtils.e(e.getMessage());
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource, int i, int i1) {
        try {
            //清楚表
            for (Class<? extends BaseEntity> entity : table) {
                TableUtils.dropTable(connectionSource, entity, true);
            }
            //重建表
            onCreate(sqLiteDatabase, connectionSource);
        } catch (Exception e) {
            LogUtils.e(e.getMessage());
        }
    }
}
